package com.wondertek.poms.image.mqListener;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.wondertek.poms.common.constant.Constants;
import com.wondertek.poms.common.exception.BusinessException;
import com.wondertek.poms.common.exception.MessageCodes;
import com.wondertek.poms.core.service.IPcImageSrcRulesService;
import com.wondertek.poms.core.service.IPcImageTaskService;
import com.wondertek.poms.core.service.IPcImageTransRulesService;
import com.wondertek.poms.dao.po.PcImageSrcRules;
import com.wondertek.poms.dao.po.PcImageTask;
import com.wondertek.poms.dao.po.PcImageTransRules;
import com.wondertek.poms.dao.po.SyncTask;
import com.wondertek.poms.image.utils.FileIO;
import com.wondertek.poms.image.utils.SyncImageUtil;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.XmlUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class StartProcess {
	// 转图临时存放路径
	@Value(value = "${trans.tmp.image.path:/tmp/syncContent}")
	private String transTmpPath;
	// 转图结束需要存放的路径
	@Value(value = "${trans.image.path:/nas/sj_nas_poms/cmvideo/image,/poms_publish/cmvideo/image,/nas/bak_poms3/cmvideo/image}")
	private String transPath;
	// 媒资与原图 nas的起始路径
	@Value(value="${syncpre.mam.path:/usr/local/syncContent/}")
    public String mamPath;
	@Autowired
	private IPcImageTaskService pcImageTaskService;
	@Autowired
    private AmqpTemplate amqpTemplate;
//    @Resource(name = "imageBackQueue")
//    private Queue imageBackQueue;
    @Autowired
    private IPcImageSrcRulesService imageSrcRulesService;
//    @Autowired
//    private IPcImageTransRulesDao imageTransRulesDao;
    @Autowired
    private IPcImageTransRulesService imageTransRulesService;

    @Async(value = "threadPoolA")
    public void fastProcess(String message){
        process(message);
    }

    public void process(String message) {
    	SyncTask st = JSON.parseObject(message, SyncTask.class);
    	boolean isSuccess = true;
    	try {
    		PcImageTask tt = saveTask(st);
    		mainProcess(tt, st);
    		log.info("内容转图主流程|业务数据：" + tt.getContentId() + " 转图业务成功。");
        } catch (Exception e) {
        	isSuccess = false;
            log.info("内容转图主流程|转图任务:" + st, e);
        } finally {
        	callback(st, isSuccess);
        }
    }
    
    private void callback(SyncTask st, boolean success) {
		log.info("内容同步主流程|业务数据：" + st.getContentId() + "媒资id：" + st.getAccessId() + "同步是否成功：" + success);
		st.setSuccess(success);
		amqpTemplate.convertAndSend(Constants.QUEUE_TRANS_IMG_BACK, JSON.toJSONString(st));
	}
    
    /**
     * <p><b>Title:</b> saveTask</p>
     * <p><b>Description:</b> 保存转图任务</p>
     * @author douzi
     * @param tt
     */
    private PcImageTask saveTask(SyncTask tt) {
		PcImageTask task = new PcImageTask();
		BeanUtil.copyProperties(tt, task);
		PcImageTask.putTimeAndUser(task);
		PcImageTask pcit = pcImageTaskService.save(task);
		return pcit;
	}

	/**
     * <p><b>Title:</b> mainProcess</p>
     * <p><b>Description:</b> 主业务入口</p>
     *
     * @param st
     * @author douzi
     */
    void mainProcess(PcImageTask tt, SyncTask st) {
    	if ("2".equals(tt.getOprCode()) || "4".equals(tt.getOprCode())) {
    		if (!("," + tt.getUpdateFields() + ",").contains(",3,")) {
    			log.error("内容转图主流程|转图任务:" + tt.getContentId() + "|媒资更新任务没有图片变更：" + tt.getUpdateFields());
    			setMessage(tt, "媒资更新任务没有图片变更");
//        		throw new BusinessException(MessageCodes.M980907);
    			return;
    		}
    	}
    	
    	if ("3".equals(tt.getOprCode())) {
			log.error("内容转图主流程|转图任务:" + tt.getContentId() + "|操作类型（3）删除，不做处理");
			setMessage(tt, "操作类型（3）删除，不做处理");
//    		throw new BusinessException(MessageCodes.M980908);
			return;
    	}
    	
    	List<String> imgs = getImgList(tt);
    	String srcImgPath = getImgPath(tt);
    	String tempImgPath = getTempImgPath(tt);

    	List<PcImageSrcRules> isrs = imageSrcRulesService.findAll(new PcImageSrcRules());
    	
    	imgs.stream().parallel().forEach(srcImgName -> {
    		this.scImgToTrans(tt, srcImgPath, srcImgName, tempImgPath, isrs);
    	});
    }

	/**
     * <p><b>Title:</b> getAssetID</p>
     * <p><b>Description:</b> 获取原图列表</p>
     * @author douzi
     * @param tt
     * @return
     * @throws IOException 
     */
    private List<String> getImgList(PcImageTask tt) {
    	String mamXmlPath = getXmlPath(tt);
    	
    	File file = new File(mamXmlPath);
    	if (!file.exists()) {
    		log.info("Metadata_M.xml not exists:" + mamXmlPath);
    		setMessage(tt, "Metadata_M.xml not exists");
    		throw new BusinessException(MessageCodes.M980905);
    	}
    	Document doc = XmlUtil.readXML(file);
    	NodeList nodes = XmlUtil.getNodeListByXPath("//DisPlayFile/DpFileName/node()", doc);
    	
    	
    	
    	List<String> scImgs = new ArrayList<String>();
    	for (int i = 0; i < nodes.getLength(); i++) {
			String nodeValue = nodes.item(i).getNodeValue();
			String name = nodeValue.substring(0, nodeValue.lastIndexOf("."));
			if (name.endsWith("_sc")) {
				scImgs.add(nodeValue);
			}
		}
    	if (scImgs.size() == 0) {
    		setMessage(tt, "上游系统没有原图");
    		throw new BusinessException(MessageCodes.M980906);
    	}
    	
		return scImgs;
	}

	/**
	 * <p><b>Title:</b> setMessage</p>
	 * <p><b>Description:</b> 设置错误信息</p>
	 * @author douzi
	 * @param tt
	 */
	private void setMessage(PcImageTask tt, String message) {
		PcImageTask pcit = pcImageTaskService.get(tt.getId());
		pcit.setMessage(message);
		pcImageTaskService.save(pcit);
	}

	/**
	 * <p><b>Title:</b> getPath</p>
	 * <p><b>Description:</b> 获取xml路径</p>
	 * @author douzi
	 * @param tt
	 * @return
	 */
	private String getXmlPath(PcImageTask tt) {
		String contentId = tt.getContentId();
    	String cPath = "/zhengshi/" + contentId.substring(0, 4) + "/" + contentId.substring(4, 7)
				+ "/" + contentId.substring(7, 10);
    	String mamXml = mamPath + cPath + File.separator + 
    			tt.getContentId() + File.separator + Constants.syncFile_baseName;
		return mamXml;
	}
	
	/**
	 * <p><b>Title:</b> getPath</p>
	 * <p><b>Description:</b> 获取image路径</p>
	 * @author douzi
	 * @param tt
	 * @return
	 */
	private String getImgPath(PcImageTask tt) {
		String contentId = tt.getContentId();
    	String cPath = "/zhengshi/" + contentId.substring(0, 4) + "/" + contentId.substring(4, 7)
				+ "/" + contentId.substring(7, 10);
    	String mamXml = mamPath + cPath + File.separator + 
    			tt.getContentId() + File.separator + Constants.image_baseName;
		return mamXml;
	}
	

    private String getTempImgPath(PcImageTask tt) {
    	String contentId = tt.getContentId();
    	String cPath = "/" + contentId.substring(0, 4) + "/" + contentId.substring(4, 7)
				+ "/" + contentId.substring(7, 10);
    	String nas1 = transPath.split(",")[0];
		String tmpImgPath = nas1 + cPath + File.separator + 
    			tt.getContentId() + File.separator + Constants.image_baseName;
		return tmpImgPath;
	}
        
    private void scImgToTrans(PcImageTask tt, String srcImgPath, String srcImgName, String tempImgPath, List<PcImageSrcRules> isrs) {
    	for (PcImageSrcRules isr : isrs) {
    		if (!srcImgName.contains(isr.getSrcRuleCode())) {
    			log.info("内容转图主流程|原图名称:" + srcImgName + "|原图规则名:" + isr.getSrcRuleName() + "|不属于此名称规则:"  + isr.getSrcRuleCode());
    			continue;
    		}
    		
    		// 获取规则详情
    		List<PcImageTransRules> itrs = getTransRules(tt, isr.getId());
    		for (PcImageTransRules itr : itrs) {
    			String transImgName = transImgName(tt.getLastModifyTime(), srcImgName, 
    					isr.getSrcRuleName(), itr.getTransRuleName(), itr.getType());
    			
    			log.info("内容转图主流程|原图名称:" + srcImgName + "|原图规则编码:" + isr.getSrcRuleCode() + 
    					"|转图规则名称:" + itr.getTransRuleName() + "|转图类型:" + itr.getType() + 
    					"|原图路径:" + srcImgPath + File.separator + srcImgName +
    					"|转图路径:" + tempImgPath + File.separator + transImgName);
    			
    			boolean isSuccess = SyncImageUtil.scaleImage(
    					srcImgPath + File.separator + srcImgName, 
    					tempImgPath + File.separator + transImgName,
    					itr.getWidth(),
    					itr.getHeight(),
    					true,
    					itr.getType(),
    					tempImgPath);
    			
    			if (isSuccess) {
        			log.info("内容转图主流程" + transImgName + "转图成功");
    				copyNas(tempImgPath, transImgName, tt.getContentId());
    			}
    		};
    	};
    }
    
    /**
     * <p><b>Title:</b> getTransRules</p>
     * <p><b>Description:</b> 所谓的个性化转图，都转全量，只是在发布xml中有差异</p>
     * @author douzi
     * @param tt
     * @param id
     * @return
     */
    private List<PcImageTransRules> getTransRules(PcImageTask tt, Long id) {
		PcImageTransRules rs = new PcImageTransRules();
		rs.setImageSrcId(id);
		return imageTransRulesService.findAll(rs);
//    	if ("4".equals(tt.getPaltform())) {
//    	}
    	
//    	Specification<PcImageTransRules> whereClause = getWhereClause(tt);
//    	return imageTransRulesDao.findAll(whereClause);
    }
    
    @SuppressWarnings("serial")
	private Specification<PcImageTransRules> getWhereClause(PcImageTask tt) {
		return new Specification<PcImageTransRules>() {
			@Override
			public Predicate toPredicate(Root<PcImageTransRules> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicate = new ArrayList<>();
				predicate.add(cb.equal(root.get("platform"), "4"));
				
				if(!Strings.isNullOrEmpty(tt.getPlatform())) {
					predicate.add(cb.or(cb.equal(root.get("platform"), tt.getPlatform())));
				}

				predicate.add(cb.equal(root.get("deleted"),"0"));
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		};
	}
    
    private void copyNas(String tempImgPath, String transImgName, String contentId) {
		String[] aa = transPath.split(",");
		String cPath = File.separator + contentId.substring(0, 4) + File.separator + contentId.substring(4, 7)
				+ File.separator + contentId.substring(7, 10);
		// 临时存储转图位置
		String tmpImg = tempImgPath + File.separator + transImgName;
		if (aa.length > 1) {
			for (int i = 1; i < aa.length; i++) {
				String transImg = aa[i] + cPath + File.separator + transImgName;
				FileIO.fileCopy(tmpImg, transImg, true);
				log.info("内容转图主流程|拷贝nas:" + transImg + " 成功");
			}
		}
	}
    
    public static void main(String[] args) {
//    	File file = new File("/tmp/syncContent/zhengshi/1504/479/719/1504479719/display/");
//		if (file.exists()) {
//			log.info("内容转图主流程|删除临时图片:" + file.delete());
//		}
    	
    	String syncTask = "{\"syncTime\":\"2020-12-16T16:12:37.029\",\"accessPlatformId\":\"89\",\"needBc\":\"0\",\"cpId\":\"800033\",\"oprCode\":\"1\",\"updateFields\":\"null\",\"contentId\":\"5500321138\",\"priority\":\"0\",\"distResult\":\"1\",\"version\":\"1.0\",\"accessId\":\"89\",\"accessPlatformType\":\"89\",\"basePath\":\"/zhengshi/5500/321/138\",\"accessSeq\":\"1000012015031315114323900239\",\"assetId\":\"5101042938\",\"accessPwd\":\"D022646351048AC0BA397D12DFAFA304\",\"lastModifyTime\":\"202010182225\",\"offlineStatus\":0,\"id\":1153,\"servType\":\"01\",\"oprTime\":\"20201216041236\"}";
    	SyncTask st = JSON.parseObject(syncTask, SyncTask.class);
    	System.out.println(st.toString());
	}
	
    /**
     * <p><b>Title:</b> copyFile</p>
     * <p><b>Description:</b> copy转图到发布路径</p>
     * @author douzi
     * @param src
     * @param dest
     * @throws IOException
     */
	public void copyFile(String src, String dest) {
		FileInputStream in = null;
		FileOutputStream out = null;
		try {
			in = new FileInputStream(src);
			File file = new File(dest);
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
			}
			if (!file.exists()) {
				file.createNewFile();
			}
			out = new FileOutputStream(file);
			int c;
			byte buffer[] = new byte[1024];
			while ((c = in.read(buffer)) != -1) {
				for (int i = 0; i < c; i++)
					out.write(buffer[i]);
			}
		} catch (IOException e) {
			log.info("内容转图主流程|拷贝nas:" + src + " 失败", e);
			throw new BusinessException(MessageCodes.M980909, "内容转图主流程|拷贝nas:" + src + " 失败");
		} finally {
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				log.info("内容转图主流程|关流失败", e);
				throw new BusinessException(MessageCodes.M980909, "IOException 内容转图主流程|关流失败" + src);
			}
		}
	}
	
	/**
	 * <p><b>Title:</b> transImgName</p>
	 * <p><b>Description:</b> 转图后的名称</p>
	 * @author douzi
	 * @param modifyTime  转图时间戳
	 * @param srcImgName  原图名称
	 * @param srcRulerName  原图规则名称
	 * @param transRuleName 转图规则名称
	 * @param type jpg webp
	 * @return
	 */
	public String transImgName(String modifyTime, String srcImgName, 
			String srcRulerName, String transRuleName, String type) {
		if (StringUtils.isBlank(modifyTime) 
				|| StringUtils.isBlank(srcImgName) 
				|| StringUtils.isBlank(transRuleName) 
				|| StringUtils.isBlank(type)) {
			log.error("内容转图主流程|关键数据为空|modifyTime:" + modifyTime + 
					"|srcName:" + srcImgName + "|transRuleName:" + transRuleName + 
					"|type:" + type);
			return null;
		}
		
		String name = modifyTime + "_" 
				+ srcImgName.substring(0, srcImgName.indexOf(srcRulerName))
				+ transRuleName + "." + type;
		return name;
	}
}
